package fstvis;

public class Field {
	/**
	 * Field defines things from index 0
	 */
	private double[][] field;
	private int ni, nj;
	private boolean v;
	
	public Field(int ni, int nj, boolean v) {
		this.ni = ni;
		this.nj = nj;
		this.v = v;
		
		this.field = new double[ni][nj];
		if (this.v)
			System.out.println("Defining field = field(" + ni + ", " + nj + ")");
	}

	public Field(int ni, int nj) {
		this.ni = ni;
		this.nj = nj;
		this.v = false;
		
		this.field = new double[ni][nj];
	}
	
	public int getLength() {
		return ni*nj;
	}

	public int[] getSize() {
		int[] i = new int[2];
		i[0] = ni; i[1] = nj;
		return i;
	}
	
	public void setValue(int i,int j, double val) {
		if (i >= 0 && i < ni && j >= 0 && j < nj) {
			if (this.v) System.out.println("fld(" + i + ", " + j + ") = " + val);
			this.field[i][j] = val;
		}
	}

	public double value(int i, int j) throws IndexOutOfBoundsException {
		if (i >= 0 && i < ni && j >= 0 && j < nj) {
			return this.field[i][j];
		} else {
			throw new IndexOutOfBoundsException();
		}
	}
	
	public double value(int x) throws IndexOutOfBoundsException {
		int[] index = Field1D.convert1DIndexTo2D(ni, nj, x);
		
		int i = index[0];
		int j = index[1];

		if (i >= 0 && i < ni && j >= 0 && j < nj) {
			if (this.v) System.out.println("Returning fld(" + x + ") = fld(" + i + ", " + j + ") = " + this.field[i][j]);
			return this.field[i][j];
		} else {
			throw new IndexOutOfBoundsException(new String("Requested (" + i + ", " + j + "), max bounds = (" + ni + ", " + nj + ")"));
		}
	}
	
	public Field1D getField1D() {
		return new Field1D(this, ni, nj);
	}

	public double[][] getField() {
		return this.field;
	}

	public static void main(String[] args) {
		

		int ni = 3, nj = 5, x = 0;
		int i, j, i1, j1;
		int[] point;
		boolean err = false;
		
		// First, test the conversion functions
		//System.out.println("Testing field gettings and setters.");
		i = 2; j = 4;
		x = Field1D.convert2DIndexTo1D(ni, nj, i, j);
		//System.out.println("ni = " + ni + ", nj = " + nj);
		//System.out.println("(" + i + ", " + j + ") = (" + x + ")");
		point = Field1D.convert1DIndexTo2D(ni, nj, x); i1 = point[0]; j1 = point[1];
		//System.out.println("(" + x + ") = (" + i + ", " + j + ")");
		if (i != i1 || j != j1) {
			System.out.println("Error, coordinate conversion failed!");
			err = true;
		}
		
		Field f = new Field(ni, nj);
		double val = 0, val1 = 0, val2 = 0;

		for (i=0; i<ni; i++) {
			for (j=0; j<ni; j++) {
				val = i*nj + j; // could be any thing
				f.setValue(i, j, val);

				x = Field1D.convert2DIndexTo1D(ni, nj, i, j);
				
				if (f.value(i, j) != val) {
					System.out.println("Warning, value not properly set, f(" + i + ", " + j + ") != " + val);
				}
				try {
					val1 = f.value(i, j);
					val2 = f.value(x);
					if (val1 != val2) { 
						System.out.println("Warning, gettings returning difference values: (" + i + ", " + j + ") = " + val + ", " +
								" f.value(" + i + ", " + j + ") = " + val1 + ", " +
								"f.value(" + x + ") = " + val2);
						err = true;
					}
				} catch (IndexOutOfBoundsException ex) {
					//System.err.println(ex);
					ex.printStackTrace();
				}
			}
		}

		Field1D f1d = f.getField1D();

		for (i=0; i<ni; i++) {
			for (j=0; j<ni; j++) {
				x = Field1D.convert2DIndexTo1D(ni, nj, i, j);
				if (f.value(i,j) != f1d.value(x)) {
					System.out.println("Warning, values f(" + i + ", " + j + ") != f1d(" + x + ")");
				}
			}
		}
		
		if (err)
			System.out.println("Field tests failed.");

	}
}
